package cz.matasek.dbLogger.gui;

import cz.matasek.dbLogger.Settings;
import cz.matasek.dbLogger.model.Database;
import cz.matasek.dbLogger.model.DateTime;
import cz.matasek.dbLogger.model.Table;
import cz.matasek.dbLogger.sql.SQLStatement;
import java.io.File;
import java.sql.ResultSet;
import java.util.Comparator;
import java.util.Date;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 * This panel contains form for querying history tables.
 *
 * @author Luboš Matásek
 */
public class HistoryPanel extends javax.swing.JPanel implements Refreshable {

    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = -4117273985665302528L;
    /**
     * The database object.
     */
    private Database database;
    /**
     * SQL query, which has returned the current result.
     */
    private String sqlQuery;
    /**
     * Table model of the historical query.
     */
    private HistoricalQueryResult tableModel;

    /**
     * Creates a new <code>HistoryPanel</code>.
     *
     * @param database the database
     */
    public HistoryPanel(Database database) {
        this.database = database;

        initComponents();

        refresh();
    }

    @Override
    public void refresh() {
        _tables.setModel(new DefaultComboBoxModel(
                database.getTablesWithHistory().toArray()));

        if (database.getTablesWithHistory().size() > 0) {
            _searchButton.setEnabled(true);
        } else {
            _searchButton.setEnabled(false);
        }
    }

    /**
     * Creates a historical table model from the specified result set.
     *
     * @param historicalTableResult the historical query result set
     * @param tableName the name of the table
     * @param dateTime the date and time of the historical view
     */
    public void setHistoricalTableContent(ResultSet historicalTableResult,
            String tableName, DateTime dateTime) {
        tableModel = new HistoricalQueryResult(
                historicalTableResult, tableName, dateTime);
        _historicalTable.setModel(tableModel);

        TableRowSorter<TableModel> sorter =
                new TableRowSorter<TableModel>(tableModel);

        Comparator comparator = new UniversalComparator();
        for (int colIndex = 0; colIndex < tableModel.getColumnCount(); ++colIndex) {
            sorter.setComparator(colIndex, comparator);
        }

        _historicalTable.setRowSorter(sorter);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        _tables = new javax.swing.JComboBox();
        _tablesLabel = new javax.swing.JLabel();
        _dateTimeLabel = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        _historicalTable = new javax.swing.JTable();
        _searchButton = new javax.swing.JButton();
        _dateTime = new javax.swing.JSpinner();
        _sqlScriptButton = new javax.swing.JButton();
        _xmlExport = new javax.swing.JButton();
        _htmlExport = new javax.swing.JButton();

        setMinimumSize(new java.awt.Dimension(595, 372));
        setPreferredSize(new java.awt.Dimension(595, 372));

        _tablesLabel.setText("Table");

        _dateTimeLabel.setText("Date and Time");

        jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
        jScrollPane1.setMinimumSize(new java.awt.Dimension(580, 273));
        jScrollPane1.setPreferredSize(new java.awt.Dimension(580, 273));

        _historicalTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        jScrollPane1.setViewportView(_historicalTable);

        _searchButton.setText("Search");
        _searchButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _searchButtonActionPerformed(evt);
            }
        });

        _dateTime.setModel(new javax.swing.SpinnerDateModel());
        _dateTime.setEditor(new javax.swing.JSpinner.DateEditor(_dateTime, "yyyy-MM-dd HH:mm:ss"));

        _sqlScriptButton.setText("Show SQL");
        _sqlScriptButton.setEnabled(false);
        _sqlScriptButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _sqlScriptButtonActionPerformed(evt);
            }
        });

        _xmlExport.setText("Export XML");
        _xmlExport.setEnabled(false);
        _xmlExport.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _xmlExportActionPerformed(evt);
            }
        });

        _htmlExport.setText("Export HTML");
        _htmlExport.setEnabled(false);
        _htmlExport.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _htmlExportActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 689, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(_tablesLabel)
                            .addComponent(_dateTimeLabel))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(_tables, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(_dateTime, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(50, 50, 50)
                                .addComponent(_searchButton)
                                .addGap(18, 18, 18)
                                .addComponent(_sqlScriptButton)
                                .addGap(18, 18, 18)
                                .addComponent(_xmlExport)
                                .addGap(18, 18, 18)
                                .addComponent(_htmlExport)))
                        .addGap(13, 13, 13)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(_tablesLabel)
                    .addComponent(_tables, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(_dateTimeLabel)
                    .addComponent(_dateTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(_sqlScriptButton)
                    .addComponent(_searchButton)
                    .addComponent(_xmlExport)
                    .addComponent(_htmlExport))
                .addGap(18, 18, 18)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 273, Short.MAX_VALUE)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Shows the historical content of a table.
     *
     * @param evt action event
     */
    private void _searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__searchButtonActionPerformed
        String tableName =
                ((Table) _tables.getSelectedItem()).getName();
        DateTime dateTime =
                new DateTime((Date) _dateTime.getValue());

        setHistoricalTableContent(
                database.getConnection().getHistoricalTableContent(tableName, dateTime),
                tableName, dateTime);

        sqlQuery = SQLStatement.getLastSQL();
        _sqlScriptButton.setEnabled(true);
        _xmlExport.setEnabled(true);
        _htmlExport.setEnabled(true);
}//GEN-LAST:event__searchButtonActionPerformed

    /**
     * Shows the SQL query of the current result.
     *
     * @param evt action event
     */
    private void _sqlScriptButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__sqlScriptButtonActionPerformed
        Dialog.SQLQuery(sqlQuery);
    }//GEN-LAST:event__sqlScriptButtonActionPerformed

    /**
     * Exports the result into the XML.
     *
     * @param evt action event
     */
    private void _xmlExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__xmlExportActionPerformed
        JFileChooser fc = new JFileChooser();
        if (fc.showSaveDialog(Gui.getInstance()) != JFileChooser.APPROVE_OPTION) {
            return;
        }

        try {
            File xmlFile = fc.getSelectedFile();

            Transformer transformer =
                    TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");

            DOMSource source = new DOMSource(tableModel.getXML());
            StreamResult result = new StreamResult(xmlFile);
            transformer.transform(source, result);
        } catch (TransformerException ex) {
            Dialog.error(ex.getMessage());
        }
    }//GEN-LAST:event__xmlExportActionPerformed

    /**
     * Exports the result into the HTML.
     *
     * @param evt action event
     */
    private void _htmlExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__htmlExportActionPerformed
        JFileChooser fc = new JFileChooser();
        if (fc.showSaveDialog(Gui.getInstance()) != JFileChooser.APPROVE_OPTION) {
            return;
        }

        try {
            File xmlFile = File.createTempFile("logger", null);

            Transformer xmlTransformer =
                    TransformerFactory.newInstance().newTransformer();

            DOMSource domSource = new DOMSource(tableModel.getXML());
            StreamResult xmlResult = new StreamResult(xmlFile);
            xmlTransformer.transform(domSource, xmlResult);


            File xsltFile = new File(
                    Settings.get(Settings.Key.XSL_DIRECTORY) + File.separator +
                    Settings.get(Settings.Key.XSL_HISTORY));
            File htmlFile = fc.getSelectedFile();

            Transformer htmlTransformer =
                    TransformerFactory.newInstance().newTransformer(
                    new StreamSource(xsltFile));
            xmlTransformer.setOutputProperty(OutputKeys.INDENT, "yes");

            StreamSource xmlSource = new StreamSource(xmlFile);
            StreamResult htmlResult = new StreamResult(htmlFile);
            htmlTransformer.transform(xmlSource, htmlResult);
        } catch (Exception ex) {
            Dialog.error(ex.getMessage());
        }
    }//GEN-LAST:event__htmlExportActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JSpinner _dateTime;
    private javax.swing.JLabel _dateTimeLabel;
    private javax.swing.JTable _historicalTable;
    private javax.swing.JButton _htmlExport;
    private javax.swing.JButton _searchButton;
    private javax.swing.JButton _sqlScriptButton;
    private javax.swing.JComboBox _tables;
    private javax.swing.JLabel _tablesLabel;
    private javax.swing.JButton _xmlExport;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables
}
